﻿using System;
using EP.Base.BaseService.Manager.Config;
using EP.Base.BaseService.Manager.Config.Enum;
using EP.Base.BaseService.Manager.Interface.Business;
using EP.Base.BaseService.Manager.Interface.Common;
using EP.Base.BaseService.Manager.Interface.Data;
using EP.Base.BaseService.Manager.Model.Entity;
using EP.Base.TaskTools;

namespace EP.Base.BaseService.Manager.Business
{
    public class EsMaintainTask:IEsMaintainTask
    {
        private readonly ILog _log;
        private readonly IEsTaskConfigs _esTaskConfigs;
        private readonly IEsIndexHandelTaskRepertory _handelTaskRepertory;
        private readonly ITaskRunLogs _taskRunLogs;
        public EsMaintainTask(ILog log, IEsTaskConfigs esTaskConfigs, IEsIndexHandelTaskRepertory handelTaskRepertory, ITaskRunLogs taskRunLogs)
        {
            _log = log;
            _esTaskConfigs = esTaskConfigs;
            _handelTaskRepertory = handelTaskRepertory;
            _taskRunLogs = taskRunLogs;
        }

        /// <summary>
        /// 开始执行所有检测任务
        /// </summary>
        /// <returns>执行是否成功</returns>
        public bool ExecCheckAllTask()
        {

            //所有任务
            var tasks = _esTaskConfigs.GetAll();
            _log.InfoFormat("读取到任务数量:{0}",tasks==null?0:tasks.Count);
            var normalTaskHandle = new NormalTaskHandle<EsTaskConfig>(tasks,
                       n =>
                       {
                           try
                           {
                               var result=RuanTask(n);
                               _log.DebugFormat("任务{0}执行结果{1}",n.Id,result);
                           }
                           catch (Exception ex)
                           {
                               _log.Error("任务执行时异常esTaskConfigId=" + n.Id, ex);
                           }

                       },
                       EsMaintainTaskConfig.RunTaskThreadNum,
                       () => _log.Debug("所有线程执行完毕！"))
            {
                IsWait = true
            };
            normalTaskHandle.Start();
            normalTaskHandle.Dispose();
           
            return true;
        }
        /// <summary>
        /// 开始执行某个检测任务
        /// </summary>
        /// <returns>执行是否成功</returns>
        public bool ExecSingleTask(int id)
        {
            var task = _esTaskConfigs.Get(id);

            return RuanTask(task);
        }

        /// <summary>
        /// 判断任务是否需要运行
        /// </summary>
        /// <returns>是否需要运行</returns>
        private bool CheckTaskIsNeedRun(EsTaskConfig esTaskConfig)
        {
            //未开启
            if (esTaskConfig.State == (short)EnumTaskConfigState.NotStarted)
                return false;
            var dateDiff = (DateTime.Now - esTaskConfig.LastRunTime);
            
            //上次执行成功 但是还未达到执行间隔
            if (esTaskConfig.LastRunResult == (short)EnumTaskRunState.Success && dateDiff.TotalMinutes < esTaskConfig.Interval)
                return false;
            //上次执行失败 或 上次执行后已达到最大间隔
            return true;
        }

        /// <summary>
        /// 执行任务
        /// </summary>
        /// <param name="esTaskConfig"></param>
        /// <returns></returns>
        private bool RuanTask(EsTaskConfig esTaskConfig)
        {
            if (esTaskConfig == null)
                return true;

            if (!CheckTaskIsNeedRun(esTaskConfig))
                return true;

            bool result;
            //db日志
            Action<bool,string> addRunLog = (r, msg) =>
            {
                _esTaskConfigs.UpdateLastRuanInfo(new EsTaskConfig
                {
                    Id = esTaskConfig.Id,
                    LastRunLog = msg,
                    LastRunResult = (short)(r ? EnumTaskRunState.Success : EnumTaskRunState.Fail),
                    LastRunTime = DateTime.Now

                });
                _taskRunLogs.Add(new TaskRunLog
                {
                    TaskId = esTaskConfig.Id,
                    RuanTime = DateTime.Now,
                    State = (short)(r ? EnumTaskRunState.Success : EnumTaskRunState.Fail),
                    RunLog = msg
                });
            };
            try
            {
                //任务
                var task = _handelTaskRepertory.Get(esTaskConfig);
                //执行
                result = task.Exec(esTaskConfig);
                //add db log
                addRunLog(result, "正常运行结束！");
            }
            catch (Exception ex)
            {
                addRunLog(false, "执行异常！" + ex.Message);
                throw;
            }
            return result;
        }
    }
}
